﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Abp.Application.Services;
using Abp.Application.Services.Dto;
using Abp.AutoMapper;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using Abp.Web.Models;
using KelonProud.Administration.Domain.Authorization;
using KelonProud.Administration.Dtos;
using KelonProud.Administration.Dtos.SearchDto;
using KelonProud.Administration.Managers.Authorization;
using KelonProud.Extensions;
using KelonProud.Mvc;

namespace KelonProud.Administration.Services
{
    public interface INavigationAppService :IAsyncCrudAppService<NavigationOutputDto, int, PagedResultRequestDto, NavigationInputDto, NavigationInputDto>
    {
        Task<IEnumerable<object>> GetNavigationTreeJson(int? parentId, string type);
        Task<IEnumerable<object>> GetNavigationRoleTreeJson(int? roleId);

        bool RequestModule(string code);

        Task<NavigationSearchOutput> GetNavigations(NavigationSearchInput searchInput);

        Task<List<object>> GetNavigationTypes();

        void DeleteMenuByIds(string ids);

        bool JudgHasRoleByNavigationCode(string code);
    }

    [WrapResult(WrapOnSuccess = false)]
    public class NavigationAppService : KelonProudAsyncCrudAppService<Navigation,NavigationOutputDto,int, PagedResultRequestDto, NavigationInputDto, NavigationInputDto>, INavigationAppService
    {
        private readonly NavigationManager _navigationManager;
        private readonly RoleManager _roleManager;
        private readonly IUnitOfWorkManager _unitOfWorkManager;

        public NavigationAppService(IRepository<Navigation, int> repository, NavigationManager navigationManager, RoleManager roleManager, IUnitOfWorkManager unitOfWorkManager) : base(repository)
        {
            _navigationManager = navigationManager;
            _roleManager = roleManager;
            _unitOfWorkManager = unitOfWorkManager;
        }

        public override async Task<NavigationOutputDto> Save(NavigationInputDto input)
        {
            if (input.IsCreate())
                CheckCreatePermission();
            else
                CheckUpdatePermission();

            var nav = _navigationManager.GetById(input.Id)??new Navigation();
            var parent = !input.ParentId.HasValue?null: _navigationManager.GetById(input.ParentId.Value);

            if(input.Type== NavigationType.Action&&!input.ParentId.HasValue)
                throw  new Exception("类型为【功能】时必须选择上级菜单");


            nav.ActionUrl = input.ActionUrl;
            nav.Code = input.Code;
            nav.Icon = input.Icon;
            nav.Description = input.Description;
            nav.IsHide = input.IsHide;
            nav.Name = input.Name;
            nav.TenantId = AbpSession.TenantId;
            nav.Order = input.Order;
            nav.Type = input.Type;
            nav.ParentId = input.ParentId;

            nav.Id =  _navigationManager.SaveNavigation(nav);
            nav.IdPath = parent != null ? parent.IdPath + nav.Id + "-" : "-" + nav.Id + "-";
            nav.NamePath = parent != null ? parent.NamePath + " > " + nav.Name : nav.Name;
            nav.Level = (byte)(nav.Parent == null ? 1 : nav.Parent.Level + 1);
            SetChildRolePath(nav);
            await _navigationManager.SaveNavigationAsync(nav);
          
            //为菜单快速添加功能
            if (nav.Type == NavigationType.Menu)
            {
                QuickAddNavigation(nav, input);
            }

            _navigationManager.SetRoles(nav,input.RoleIds);
            _navigationManager.SetEditions(nav,input.EditionIds);

            return nav.MapTo<NavigationOutputDto>();
        }

        public async Task<IEnumerable<object>> GetNavigationTreeJson(int? parentId,string type= "menu")
        {
            var navs = await _navigationManager.GetNavigationsByParentIdAsync(parentId);

            if (type.HasValue())
            {
                navs = type == "menu" ? navs.Where(w => w.Type == NavigationType.Menu) : navs.Where(w => w.Type == NavigationType.Action);
            }

            var result = navs.Select(s => new
            {
                Id = s.Id.ToString(),
                PId = s.ParentId ?? -1,
                Name = s.Name,
                Level = s.Level
            }).ToList();

            result.Insert(0,new
            {
                Id="",
                PId=-1,
                Name="无",
                Level=(byte)1
            });

            return result;
        }

        public async Task<IEnumerable<object>> GetNavigationRoleTreeJson(int? roleId)
        {
            var navs = await _navigationManager.GetNavigationsByParentIdAsync(null);

            var result = navs.Select(s => new
            {
                Id = s.Id.ToString(),
                PId = s.ParentId ?? -1,
                Name = s.Name,
                Level = s.Level,
                Checked= s.Roles.Any(a=>a.RoleId==roleId)
            }).ToList();

            return result;
        }

        public bool RequestModule(string code)
        {
            var nav = _navigationManager.GetNavigationByCode(code);

            if (nav == null)
                return false;
            else
            {
                if (AbpSession.UserId != null)
                {
                    var userRoleIds = _roleManager.CurrentUserRoles.Select(s => s.RoleId).ToList(); ;

                    var result = nav.Roles.Any(a => userRoleIds.Any(b => b == a.RoleId));

                    //if (result)
                    //{
                    //    _moduleHisManager.AddHistory(module.Id, module.Name);
                    //}

                    return result;
                }
                else
                {
                    throw new Exception("登录失效");
                }
            }
        }

        public Task<NavigationSearchOutput> GetNavigations(NavigationSearchInput searchInput)
        {
            var result = new NavigationSearchOutput() { };
            var query = _navigationManager.Query;

            if (searchInput.Name.HasValue())
            {
                query = query.Where(w => w.Name.Contains(searchInput.Name));
            }

            if (searchInput.Code.HasValue())
            {
                query = query.Where(w => w.Code.Contains(searchInput.Code));
            }

            if (searchInput.Type.HasValue()&& searchInput.Type != "-1")
            {
                query = query.Where(w => w.Type.ToString() == searchInput.Type);
            }

            result.Total = query.Count();
            result.Rows = query.Skip(searchInput.SkipCount).Take(searchInput.SearchCount).ToList()
                .Select(s => s.MapTo<NavigationOutputDto>()).ToList();

            return Task.FromResult(result);
        }

        public Task<List<object>> GetNavigationTypes()
        {
            var nameValues = typeof(NavigationType).GetEmunDictionary();

            var models = nameValues.Select(s => (object)new { Id = s.Value, Name = s.Key }).ToList();

            return Task.FromResult(models);
        }

        public void DeleteMenuByIds(string ids)
        {
            if (ids.HasValue())
            {
                var idList = ids.Split(',');
                idList.Each(e =>
                {
                    var nav = _navigationManager.GetById(e.ToInt32());

                    if (nav != null)
                    {
                        if(nav.Children.Count>0)
                            throw new  Exception("菜单{0}有下级模块，不能删除".FormatWith(nav.Name));
                        else
                        {
                            if (nav.Roles.Any())
                            {
                                nav.Roles.Each(role =>
                                {
                                    _navigationManager.DeleteNavigationRole(role);
                                });
                            }

                            if (nav.Editions.Any())
                            {
                                nav.Editions.Each(edition =>
                                {
                                    _navigationManager.DeleteNavigationEdtion(edition);
                                });
                            }

                            _navigationManager.DeleteNavigation(nav);
                        }
                    }
                });
            }
        }

        public bool JudgHasRoleByNavigationCode(string code)
        {
            var roles = _roleManager.CurrentUserRoles;
            var navigation = _navigationManager.GetNavigationByCode(code);

            if (navigation != null)
            {
              return  navigation.Roles.Any(a => roles.Any(w => w.RoleId == a.RoleId));
            }

            return false;
        }

        private void SetChildRolePath(Navigation nav)
        {
            nav.Children?.Each(e =>
            {
                e.IdPath = nav.IdPath + e.Id + "-";
                e.NamePath = nav.NamePath + " > " + e.Name;
                e.Level = (byte)(nav.Level + 1);
                SetChildRolePath(e);
            });
        }

        private void QuickAddNavigation(Navigation parent, NavigationInputDto input)
        {
            if (input.FunctionAdd)
            {
               var nav = new Navigation
                {
                    Name = "新增",
                    Code = parent.Code+"_ADD",
                    Icon = "fa fa-plus",
                    TenantId = parent.TenantId,
                    ParentId = parent.Id,
                    Order = 0,
                    Type = NavigationType.Action
               };
                OnQuickAddNavigation(nav, parent, input);
            }

            if (input.FunctionEdit)
            {
                var nav = new Navigation
                {
                    Name = "编辑",
                    Code = parent.Code + "_EDIT",
                    Icon = "fa fa-pencil",
                    TenantId = parent.TenantId,
                    ParentId = parent.Id,
                    Order = 1,
                    Type = NavigationType.Action
                };
                OnQuickAddNavigation(nav, parent, input);
            }

            if (input.FunctionDelete)
            {
                var nav = new Navigation
                {
                    Name = "删除",
                    Code = parent.Code + "_DELETE",
                    Icon = "fa fa-remove",
                    TenantId = parent.TenantId,
                    ParentId = parent.Id,
                    Order = 3,
                    Type = NavigationType.Action
                };
                OnQuickAddNavigation(nav, parent, input);
            }
        }

        private void OnQuickAddNavigation(Navigation nav,Navigation parent,NavigationInputDto input)
        {
            if (!_navigationManager.CheckNavigationActionExits(nav))
            {
                nav.Id = _navigationManager.SaveNavigation(nav);
                nav.IdPath = parent != null ? parent.IdPath + nav.Id + "-" : "-" + nav.Id + "-";
                nav.NamePath = parent != null ? parent.NamePath + " > " + nav.Name : nav.Name;
                nav.Level = (byte)(nav.Parent == null ? 1 : nav.Parent.Level + 1);
                SetChildRolePath(nav);
                _navigationManager.SaveNavigation(nav);
                _navigationManager.SetRoles(nav, input.RoleIds);
                _navigationManager.SetEditions(nav, input.EditionIds);
            }
        }
    }
}
